<!--
  通用表单的field 孙小寒 2022-4-5
-->
<template>
  <view class="m-field-view" :class="isLabelLine? 'm-field-view-column':''" @tap="tap">
    <view v-if="$slots['left-view'] || label" class="label-view"
          :style="isLabelLine?'margin-bottom: 0.25em;':`width: ${labelWidth};`">
      <slot name="left-view" :field="ctx">
        <template v-if="label">
          <view v-if="required && !mask" class="required-view">*</view>
          {{ label }}
        </template>
      </slot>
    </view>
    <view class="field-view" style="flex-wrap: nowrap;">
      <slot name="input-view" :field="ctx">
        <view class="input-view" :style="`text-align: ${inputAlign}`"
              :class="error && errorMessage?'error-input-view':''">
          <template v-if="type=='textarea'">
          <textarea
            :value="modelValue"
            @input="input"
            @focus="focus"
            @blur="blur"
            :placeholder="mask?'':placeholder"
            :maxlength="maxlength"
          />
          </template>
          <template v-else-if="type=='checkbox'">
            <m-checkbox
              class="form-input"
              :options="options"
              :model-value="modelValue"
              @update:model-value="toEmit"
            />
          </template>
          <template v-else-if="type=='select'">
            <m-select
              :options="options"
              :model-value="modelValue"
              :multiple="multiple"
              :value-key="valueKey"
              :label-key="labelKey"
              :jump-selection="jumpSelection"
              @update:model-value="toEmit"
              @change="change"
              :placeholder="mask?'':placeholder"
            />
          </template>
          <template v-else-if="isPicker">
            <m-picker
              :options="options"
              :type="type"
              :format="format"
              :model-value="modelValue"
              :placeholder="mask?'':placeholder"
              @update:model-value="toEmit"
            />
          </template>
          <template v-else>
            <input
              :type="type"
              :value="modelValue"
              @input="input"
              @focus="focus"
              @blur="blur"
              :maxlength="maxlength"
              :placeholder="mask?'':placeholder"
            />
          </template>
          <view v-show="clearable" class="clear-view" @tap="clear">
            <van-icon name="clear"/>
          </view>
          <view v-show="comment" @tap="showComment" class="clear-view">
            <van-icon name="question"/>
          </view>
          <template v-if="$slots['right-view']">
            <view class="right-view">
              <slot name="right-view" :field="ctx"/>
            </view>
          </template>
          <view v-if="isLink" style="padding: 0 0 0 5px;">
            <van-icon name="arrow"/>
          </view>
        </view>
        <view v-if="error && errorMessage" class="err-msg-view" :style="`text-align: ${errorMessageAlign};`">
          {{ errorMessage }}
        </view>
        <view v-if="wordLimit" class="zs-view">{{ wordLimit }}</view>
        <view v-if="mask" class="mask-view" :style="disabled?'opacity: 0.3; background-color: white;':''"/>
      </slot>
    </view>
  </view>
</template>
<script setup>
import {computed, ref, useSlots} from 'vue'

const props = defineProps({
  modelValue: {
    required: true,
    default: () => ''
  },
  type: {
    type: String,
    default: () => 'text'
  },
  isLabelLine: {
    type: Boolean,
    default: () => false
  },
  labelWidth: {
    type: String,
    default: () => '5em'
  },
  required: {
    type: Boolean,
    default: () => false
  },
  label: {
    type: String,
    default: () => ''
  },
  clearable: {
    type: Boolean,
    default: () => true
  },
  autosize: {
    type: Boolean,
    default: () => false
  },
  maxlength: {
    type: Number,
    default: () => -1
  },
  placeholder: {
    type: String,
    default: () => ''
  },
  comment: {
    type: String,
    default: () => ''
  },
  inputAlign: {
    type: String,
    default: () => 'left'
  },
  disabled: {
    type: Boolean,
    default: () => false
  },
  readonly: {
    type: Boolean,
    default: () => false
  },
  isLink: {
    type: Boolean,
    default: () => false
  },
  showWordLimit: {
    type: Boolean,
    default: () => false
  },
  error: {
    type: Boolean,
    default: () => false
  },
  errorMessage: {
    type: String,
    default: () => ''
  },
  errorMessageAlign: {
    type: String,
    default: () => 'left'
  },
  options: {
    type: [Array, Object],
    default: () => []
  },
  format: {
    type: String,
  },
  valueKey: {
    type: String,
  },
  labelKey: {
    type: String,
  },
  jumpSelection: {
    type: Boolean,
  },
  multiple: {
    type: Boolean,
  },
})
const slots = useSlots()

const isPicker = computed(() => {
  return ['date', 'datetime', 'year-month'].includes(props.type)
})
const placeholder = computed(() => {
  if (props.placeholder instanceof Function) {
    return props.placeholder()
  }
  return props.placeholder
})

const ctx = computed(() => {
  return {
    ...props,
    clearable: clearable.value,
    mask: mask.value,
    wordLimit: wordLimit.value,
    isFocus: isFocus.value,
    clear,
    input,
    toEmit,
  }
})

// const isLink = computed(() => {
//   return props.isLink || isPicker.value
// })
const clearable = computed(() => {
  const notNull = props.modelValue instanceof Array ? (props.modelValue.length) : props.modelValue
  const clearable = isFocus.value || props.type === 'select'
  return props.clearable && notNull && clearable && !props.readonly && !props.disabled && !['checkbox', 'radio'].includes(props.type)
})

const mask = computed(() => {
  return props.readonly || props.disabled
})

const wordLimit = computed(() => {
  if (props.maxlength > 0 && props.showWordLimit) {
    if (!props.modelValue) return `0/${props.maxlength}`
    return `${props.modelValue.length}/${props.maxlength}`
  }
  return ''
})

const emit = defineEmits(['update:modelValue', 'change', 'input', 'focus', 'blur', 'tap'])

const isFocus = ref(false)

function focus(e) {
  isFocus.value = true
  emit('focus', e)
}

function blur(e) {
  isFocus.value = false
  emit('blur', e)
}

function tap(e) {
  emit('tap', e)
}

function showComment() {
  wx.showModal({
    title: '说明',
    content: props.comment,
    showCancel: false
  })
}

function clear() {

  let value = ''
  if (props.modelValue instanceof Array) value = []
  if (props.type === 'select') {
    return emit('update:modelValue', value)
  }
  toEmit(value)
}

function input(e) {
  const value = e.detail.value
  toEmit(value)
}

function change(e) {
  emit('change', e)
}

function toSelectEmit(e) {
  if (props.type === 'select') {
    emit('update:modelValue', e.modelValue)
    emit('change', e)
    emit('input', e.modelValue)
  }
}

function toEmit(e) {
  emit('update:modelValue', e)
  emit('input', e)
  if (props.type === 'select') {
    return
  }
  emit('change', e)
}
</script>
<style lang="scss">
.m-field-view {
  padding: 0.5em 0;
  background-color: white;
  display: flex;
  border-bottom: 1rpx solid #f3f3f3;
  flex-wrap: nowrap;

  .left-view {
    margin-top: 0.25em;
  }

  .label-view {
    flex-shrink: 0;
    display: flex;
    margin: 0.25em 0 0 0.25em;

    .required-view {
      color: red;
      margin-top: 0.2em;
      margin-bottom: -0.2em;
      margin-right: 0.1em;
    }
  }

  .field-view {
    flex-grow: 1;
    position: relative;

    .input-view {
      display: flex;
      align-items: center;
      flex-grow: 1;

      > .form-input, input, textarea {
        margin: 0 0 0 0.2em;
        flex-grow: 1;
      }

      input {
        border: 1rpx solid rgba(255, 255, 255, 0);
        line-height: 1em;
        border-radius: 0.5em;
        padding: 0.25em 0.5em;
        background-color: #f8f8f8;
      }

      textarea {
        border: 1rpx solid rgba(255, 255, 255, 0);
        line-height: 1em;
        border-radius: 0.5em;
        width: auto;
        height: 5em;
        padding: 0.5em;
        background-color: #f8f8f8;
      }

      .clear-view {
        padding: 0 0 0 0.3em;
        flex-shrink: 0;
        transition: all 0.3s;
      }

      .right-view {
        margin-left: 5px;
        flex-shrink: 0;
      }

    }

    .error-input-view {
      > input, textarea {
        border: 1rpx solid red;
        color: red;
        margin-bottom: 0;
      }

      > .input-view {
        margin-bottom: 0;
      }
    }

    .err-msg-view {
      color: red;
      font-size: 0.8em;
      margin-left: 0.2em;
    }

    .zs-view {
      text-align: right;
      opacity: 0.7;
      //margin-top: 0.25em;
      font-size: 0.8em;
    }

    .mask-view {
      position: absolute;
      z-index: 2;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
    }
  }
}

.m-field-view-column {
  flex-direction: column;
}
</style>
